package com.example.zce.back.controller.sys;

import com.example.zce.back.task.BaseJob;
import com.example.zce.library.common.bean.ResultMapBean;
import com.example.zce.library.common.bean.ResultTableBean;
import com.example.zce.library.data.sys.entity.BackTask;
import com.example.zce.library.data.sys.service.BackTaskService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 描述：定时任务控制器
 *
 * @author zengyz
 * @date 2018/8/5 13:49
 */
@Controller
@RequestMapping("/sys/quartz")
public class BackTaskController {

    private static Logger log = LoggerFactory.getLogger(BackTaskController.class);

    @Autowired
    private BackTaskService backTaskService;

    //加入Qulifier注解，通过名称注入bean
    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    /**
     * 首页
     * @return
     */
    @GetMapping("/index.html")
    public ModelAndView indexHtml() {
        return new ModelAndView("sys/task-index");
    }

    /**
     * 分页数据
     * @param request
     * @return
     */
    @ResponseBody
    @GetMapping(value = "/list.json")
    public ResultTableBean<BackTask> listJson(HttpServletRequest request) {
        Map params = new HashMap();
        params.put("pageNum", request.getParameter("page"));
        params.put("pageSize", request.getParameter("limit"));
        ResultTableBean<BackTask> backTaskResultTableBean = backTaskService.findByParams(params);
        for (BackTask backTask:backTaskResultTableBean.getData()) {
            int state = state(backTask.getPackagePath(), backTask.getGroupname());
            backTask.setState(String.valueOf(state));
        }
        return backTaskResultTableBean;
    }

    /**
     * 添加页面
     * @return
     */
    @GetMapping("/add.html")
    public ModelAndView addHtml() {
        return new ModelAndView("sys/task-add");
    }

    /**
     * 保存修改
     * @param backTask
     * @return
     */
    @ResponseBody
    @PostMapping("/saveupdate.json")
    public ResultMapBean saveupdateJson(BackTask backTask) {
        try {
            int i = backTaskService.saveOrUpdate(backTask);
            if (i != 0) {
                return ResultMapBean.ok();
            } else {
                return ResultMapBean.error(501, "操作失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMapBean.error(500, "系统错误");
        }
    }

    /**
     * 修改页面
     * @param request
     * @return
     */
    @GetMapping("/update.html")
    public ModelAndView updateHtml(HttpServletRequest request) {
        String id = request.getParameter("id");
        BackTask backTask = backTaskService.findById(id);
        request.setAttribute("backTask", backTask);
        return new ModelAndView("sys/task-update");
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @ResponseBody
    @PostMapping("/delete.json")
    public ResultMapBean deleteJson(String id) {
        try {
            int i = backTaskService.delete(id);
            if (i != 0) {
                return ResultMapBean.ok();
            } else {
                return ResultMapBean.error(501, "操作失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultMapBean.error(500, "系统错误");
        }
    }

    /**
     * 开始任务
     * @param id
     * @return
     */
    @ResponseBody
    @PostMapping("/start.json")
    public ResultMapBean startJson(String id){
        BackTask backTask = backTaskService.findById(id);
        if (backTask==null){
            return ResultMapBean.error(500, "未查询到该定时任务");
        }else{
            try {
                addJob(backTask.getPackagePath(),backTask.getGroupname(),backTask.getCron());
                return ResultMapBean.ok();
            } catch (Exception e) {
                return ResultMapBean.error(500, "定时任务启动失败");
            }
        }
    }

    /**
     * 重新启动任务
     * @param id
     * @return
     */
    @ResponseBody
    @PostMapping("/restart.json")
    public ResultMapBean restartJson(String id){
        BackTask backTask = backTaskService.findById(id);
        if (backTask==null){
            return ResultMapBean.error(500, "未查询到该定时任务");
        }else{
            try {
                reschedule(backTask.getPackagePath(),backTask.getGroupname(),backTask.getCron());
                return ResultMapBean.ok();
            } catch (Exception e) {
                return ResultMapBean.error(500, "定时任务启动失败");
            }
        }
    }

    /**
     * 任务停止
     * @param id
     * @return
     */
    @ResponseBody
    @PostMapping("/end.json")
    public ResultMapBean endJson(String id){
        BackTask backTask = backTaskService.findById(id);
        if (backTask==null){
            return ResultMapBean.error(500, "未查询到该定时任务");
        }else{
            try {
                pause(backTask.getPackagePath(),backTask.getGroupname());
                return ResultMapBean.ok();
            } catch (Exception e) {
                return ResultMapBean.error(500, "定时任务停止失败");
            }
        }
    }

    /**
     * 添加任务
     *
     * @param packagePath
     * @param groupname
     * @param cron
     * @throws Exception
     */
    public void addJob(String packagePath, String groupname, String cron) throws Exception {
        // 启动调度器
        scheduler.start();
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(packagePath).getClass()).withIdentity(packagePath, groupname).build();
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(packagePath, groupname).withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail, trigger);
    }

    /**
     * 停止任务
     *
     * @param packagePath
     * @param groupname
     * @throws Exception
     */
    public void pause(String packagePath, String groupname) throws Exception {
        scheduler.pauseJob(JobKey.jobKey(packagePath, groupname));
    }

    public void resume(String packagePath, String groupname) throws Exception {
        scheduler.resumeJob(JobKey.jobKey(packagePath, groupname));
    }

    /**
     * 获取定时任务状态
     *             STATE_BLOCKED 	4       阻塞
     *             STATE_COMPLETE 	2       完成
     *             STATE_ERROR 	    3       错误
     *             STATE_NONE 	    -1      不存在
     *             STATE_NORMAL 	0       正常
     *             STATE_PAUSED 	1       暂停
     * @param packagePath
     * @param groupname
     * @return
     */
    public int state(String packagePath, String groupname) {
        TriggerKey triggerKey = TriggerKey.triggerKey(packagePath, groupname);
        try {
            Trigger.TriggerState state  = scheduler.getTriggerState(triggerKey);
            if (state.name().equals("PAUSED")){
                return 1;
            }else if(state.name().equals("COMPLETE")){
                return 2;
            }else if(state.name().equals("ERROR")){
                return 3;
            }else if(state.name().equals("BLOCKED")){
                return 4;
            }else if(state.name().equals("NORMAL")){
                return 0;
            }else if(state.name().equals("NONE")){
                return -1;
            }else{
                return -2;
            }
        } catch (SchedulerException e) {
            return -2;
        }
    }

    /**
     * 重新执行任务
     * @param packagePath
     * @param groupname
     * @param cron
     * @throws Exception
     */
    public void reschedule(String packagePath, String groupname, String cron) throws Exception {
        TriggerKey triggerKey = TriggerKey.triggerKey(packagePath, groupname);
        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        // 按新的cronExpression表达式重新构建trigger
        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
        // 按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 删除任务
     * @param packagePath
     * @param groupname
     * @throws Exception
     */
    public void delete(String packagePath, String groupname) throws Exception {
        scheduler.pauseTrigger(TriggerKey.triggerKey(packagePath, groupname));
        scheduler.unscheduleJob(TriggerKey.triggerKey(packagePath, groupname));
        scheduler.deleteJob(JobKey.jobKey(packagePath, groupname));
    }

    public static BaseJob getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.newInstance();
    }
}
